package br.ufc.customJDBC.routing;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import br.ufc.customJDBC.CustomConnection;
import br.ufc.customJDBC.csv.CSVLog;

public class VariableCircularQueueRouter implements Router{

	private Collection<CustomConnection> connectionPool;
	private List<CustomConnection> allConnections;
	private Iterator<CustomConnection> iter;
	private CSVLog csv;

	public VariableCircularQueueRouter(List<CustomConnection> connectionPool, CSVLog csv, int initialNumber) {
		this.allConnections = connectionPool;
		this.connectionPool = allConnections.subList(0, initialNumber); 
		iter = connectionPool.iterator();
		this.csv = csv;
	}	

	private CustomConnection nextConnection(){
		synchronized (this) {
			if(iter.hasNext()){
				return iter.next();
			}else{
				iter = connectionPool.iterator();
				return iter.next();
			}
		}
	}
	
	public void addServer(int quantity){
		synchronized (iter) {
			connectionPool = allConnections.subList(0, connectionPool.size() + quantity);
			iter = connectionPool.iterator();
		}
	}

	@Override
	public boolean execute(String sql) throws SQLException {

		CustomConnection con = nextConnection();
		Statement statement = con.createStatement();

		long startTime = System.nanoTime();
		boolean ret = statement.execute(sql);
		long stopTime = System.nanoTime();

		String nodes = "[ " + con.getIp() + " ]";
		csv.writeLine(sql, (stopTime - startTime), 1, "execute", nodes );

		//		statement.close();
		return ret;
	}

	@Override
	public ResultSet executeQuery(String sql) throws SQLException {
		CustomConnection con = nextConnection();
		Statement statement = con.createStatement();

		long startTime = System.nanoTime();
		ResultSet ret = statement.executeQuery(sql);
		long stopTime = System.nanoTime();

		String nodes = "[ " + con.getIp() + " ]";
		csv.writeLine(sql, (stopTime - startTime), 1, "executeQuery", nodes );

		//		statement.close();
		return ret;
	}

	@Override
	public int executeUpdate(String sql) throws SQLException {
		CustomConnection con = nextConnection();
		Statement statement = con.createStatement();

		long startTime = System.nanoTime();
		int ret = statement.executeUpdate(sql);
		long stopTime = System.nanoTime();

		String nodes = "[ " + con.getIp() + " ]";
		csv.writeLine(sql, (stopTime - startTime), 1, "executeQuery", nodes );		

		//		statement.close();
		return ret;
	}
}
